import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class JavaArray {
    public static void main1(String[] args) {
        int[] arr={1,2,3,4,5,6};
        //静态初始化
        int[] arr1=new int[]{1,2,3,4,5,6};   //不仅分配了内存空间，而且完成了初始化  注意:只要写了{}，就不能字[]里面写数字
        //动态初始化
        int[] arr2=new int[10];  //仅仅只是分配了内存空间，默认初始化为0
        //可以先定义在赋值
        int[] arr3;
        arr3=new int[]{1,2,3,4,5,6};
        arr3=new int[10];
        //arr3={1,2,3};  这样写是错误的，必须要加上new int


        //遍历数组的三种方式
        //1.
        for(int i=0;i<arr3.length;i++) {      //数组名.length就可以自动求出长度
            System.out.println(arr3[i]);
        }

        //2.
        for(int x:arr1) {      //int x :数组中每个元素的类型 x是数组中的每一个元素  arr1:需要遍历的数组名  for-each遍历数组
            System.out.println(x);
        }

        //3.
        Arrays.sort(arr1);
        String ret=Arrays.toString(arr1);      //Arrays.toString(arr1)这个方法是把arr1转换成了字符串
        System.out.println(ret);
    }




    public static void main2(String[] args) {
        //两个引用指向同一个对象，通过其中任何一个引用，修改这个对象的值，另一个引用去访问的时候，也是会改变的
        int[] arr1={1,2,3,4};
        arr1[0]=99;
        int[] arr2=arr1;  //arr2接受了一个引用变量arr1，所以arr1和arr2指向了同一个对象，改变对象的值，那么arr1和arr2都会发生改变
        arr2[0]=100;
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));



        int[] array1={1,2,3,4};
        int[] array2={11,22,33,44};
        array2=array1;   //两个引用同时指向一个对象
        array1[0]=1888;  //此时没有变量引用原来array2的对象了，就会被系统回收
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));
    }




    public static void func1(int[] array) {
        array=new int[]{15,16,17};     //只是改变了形参的指向
    }
    public static void func2(int[] array) {
        array[0]=999;    //通过引用修改了原来对象的值
    }
    public static void grow(int[] array) {
        for (int i = 0; i < array.length ; i++) {
            array[i]*=2;
        }
    }

    public static int[] func3() {
        int[] array=new int[]{1,2,3,4,5,6};
        return array;
    }
    public static void main3(String[] args) {
        int[] array1={1,2,3,4};
        func1(array1);
        System.out.println(Arrays.toString(array1));
        func2(array1);
        System.out.println(Arrays.toString(array1));
        grow(array1);
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(func3()));
        System.out.println(func3());     //求得的是返回数组的地址
    }




    public static String my_toString(int[] array) {
        if(array==null) {
            return "null";
        }
        String ret="[";
        for (int i = 0; i < array.length; i++) {
            if(i!= array.length-1) {
                ret+=array[i]+", ";
            }else {
                return ret+array[i]+"]";
            }
        }
        return null;
    }

    public static int[] copyarray(int[] array) {
        int[] array1=new int[array.length];
        for (int i = 0; i < array.length ; i++) {
            array1[i]=array[i];
        }
        return array1;
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4};
        //编写方法使得数组转为一个字符串
        System.out.println(my_toString(array));

        //编写方法实现数组拷贝
        System.out.println(Arrays.toString(copyarray(array)));

        //copyof可以当做扩容来用，参数是要拷贝的数组和新数组开辟的空间大小
        System.out.println(Arrays.toString(Arrays.copyOf(array, array.length*2)));

        //arraycopy参数:拷贝来源，拷贝下标的起始位置，拷贝目的地，从目的地的那个位置开始拷贝，拷贝来源的长度
        //可以指定区间拷贝
        int[] array2=new int[array.length];
        System.arraycopy(array,0,array2,0,array.length);
        System.out.println(Arrays.toString(array2));

        //copyofrange参数:拷贝的数组，from从哪个下标开始，to到那个下标结束，结果是左闭又开，所以不会拷贝to下标的数
        System.out.println(Arrays.toString(Arrays.copyOfRange(array, 1,3)));

        //equals 判断两个数组的对象的值是否相等  注意:如果直接用array==array2判断是否相等是不对的，因为两个引用变量表示不同的地址，存的不同的对象
        System.out.println(Arrays.equals(array,array2));

        //fill 将数组的元素改为一个给定的值，也可以是有范围的
        int[] array3=new int[10];
        Arrays.fill(array3,-1);
        Arrays.fill(array3,1,3,-2);
        System.out.println(Arrays.toString(array3));

        //数组名.clone 克隆的意思就是产生一个副本
        int[] array4=array.clone();
        System.out.println(Arrays.toString(array4));
    }

    public static int[] order(int[] array) {
        int[] array1=new int[array.length];
        int left=0;
        int right= array.length-1;
        for (int i = 0; i < array.length ; i++) {
            if(array[i]%2!=0) {
                array1[left++]=array[i];
            }else {
                array1[right--]=array[i];
            }
        }
        return array1;
    }

    public static int binarySearch(int[] array,int target) {
        Arrays.sort(array);
        int left=0;
        int right=array.length-1;
        while(left<=right) {
            int mid=(left+right)/2;
            if(array[mid]<target) {
                left=mid+1;
            }else if(array[mid]>target) {
                right=mid-1;
            }else {
                return mid;
            }
        }
        return -1;
    }

    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length-1; i++) {
            boolean flag=false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j]>array[j+1]) {
                    int tmp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=tmp;
                    flag=true;
                }
                if(flag==false) {  //如果在执行第i次的时候已经有序了，在执行下一趟就不会发生交换，这时候加上flag就能直接结束，省了时间
                    return;
                }
            }
        }
    }

    public static int[] twosum(int[] nums,int target) {
        for (int i = 0; i < nums.length ; i++) {
            for (int j = ++i; j < nums.length ; j++) {
                if(nums[i]+nums[j]!=target) {
                }else {
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{-1,-1};
    }



    public static int findnumber(int[] array) {
        if(array.length==1) {
            return array[0];
        }
        Arrays.sort(array);
        int count=1;
        int i=0;
        int j=1;
        while(i<array.length) {
            while(j<array.length) {
                if(array[i]==array[j]) {
                    count++;
                    if(count>array.length/2) {
                        return array[i];
                    }
                    j++;
                }else {
                    count=1;
                    i=j++;
                }
            }
        }
        return -1;
    }

    public static int majorityElement(int[] nums) {
        int count=0;
        int tmp=nums[0];
        for (int i = 0; i < nums.length; i++) {
                if(nums[i]==tmp) {
                    count++;
                }else {
                    count--;
                }
                if(count==0) {
                    tmp=nums[i];
                    count++;
                }
        }
        return tmp;
    }


    public static boolean judgePrimeNumber(int[] array) {
        int count=0;
        for (int i = 0; i < array.length; i++) {
            if(array[i]%2!=0) {
                count++;
                if(count==3) {
                    return true;
                }
            }else {
                count=0;
            }
        }
        return false;
    }

    public static int[] singleNumbers(int[] nums) {
        List<Integer> list=new ArrayList<>();
        int[] array=new int[10000];
        int[] a=new int[2];
        for(int i=0;i<nums.length;i++) {
            int x=nums[i];
            array[x]++;
        }
        for(int i=0;i<nums.length;i++) {
            int x=nums[i];
            if(array[x]==1) {
                list.add(x);
            }
        }
        a[0]=list.get(0);
        a[1]=list.get(1);
        return a;
    }
    public static void main5(String[] args) {
        //调整数组顺序，使得奇数位于偶数之前
        int[] array={1,2,3,4,5,6};
        System.out.println( Arrays.toString(order(array)));

        //给定一个整形数组，编写方法实现二分查找
        int[] array2={1,3,5,2,4,6,8,7,9};
        Scanner sacn=new Scanner(System.in);
        int target= sacn.nextInt();
        int ret=binarySearch(array2,target);
        if(ret==-1) {
            System.out.println("没有找到该元素的下标");
        }else {
            System.out.println("找到了该元素，下标为:"+ret);
        }
        System.out.println(Arrays.binarySearch(array2,8));//库方法


        //给定一个整形数组，编写方法实现冒泡排序(升序)
        int[] array4={2,5,6,8,9,4,3};
        bubbleSort(array4);
        System.out.println(Arrays.toString(array4));


        //给定一个整形数组和一个目标值，请你在这个数组中找出两个数的和是这个目标值的数，并且返回这两个数的下标
        int[] array5={1,3,6,9};
        System.out.println(Arrays.toString(twosum(array5, 12)));


        //给定一个大小为n的正整数数组，找到其中出现次数大于n/2的数
        //简便思路:先排序，排完序之后中间的那个数就是出现最多次数的
        int[] array6={6,5,5};
        System.out.println(findnumber(array6));
        System.out.println(majorityElement(array6));

        //给定一个整数数组arr，请你判断数组中是否存在连续三个元素都是奇数的情况，如果存在返回true，不存在返回false
        int[] array7={2,4,5,3,1};
        System.out.println(judgePrimeNumber(array7));

        //给定一个整形数组，数组中有两个数出现了一次，其他出现了两次，找出这两个出现一次的数字
        int[] array8={4,1,4,6};
        int[] arr=singleNumbers(array8);
        System.out.println(Arrays.toString(arr));
    }



    //二维数组
    public static void main6(String[] args) {
        //二维数组的遍历
        //1.
        int[][] array={{1,2,3},{4,5,6}};   //遍历是一行一行的遍历
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }

        //2.
        for (int[] ret: array) {
            for (int x:ret) {
                System.out.print(x+" ");
            }
            System.out.println();
        }

        //3.
        System.out.println(Arrays.deepToString(array));
    }




    public static void main8(String[] args) {
        int[][] array=new int[2][];  //java中二维数组列可以被省略
        System.out.println(array[0]);
        System.out.println(array[1]);
        array[0]=new int[2];
        array[1]=new int[4];
        System.out.println(Arrays.deepToString(array));
    }
}
